package ide.ccf.ccproject.actions;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.ui.actions.WorkspaceAction;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.ui.PlatformUI;
import org.eclipse.core.runtime.IProgressMonitor;

import ide.ccf.ccproject.common.Utils;
import ide.ccf.ccproject.qmake.QMakeRunner;

import java.lang.reflect.InvocationTargetException;
import java.lang.InterruptedException;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IProject;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IEditorInput;

import java.util.Set;
import java.util.HashSet;
import java.util.List;


/**
 * 执行qmake操作
 * 从WorkspaceAction继承以获得访问项目资源管理器树的选择的权限
 * @author kylin
 *
 */
public class RunQMakeAction extends WorkspaceAction implements IWorkbenchWindowActionDelegate 
{
	private Set<String> projectsForQMake;
	
	/**
	 * 构造器
	 */
	public RunQMakeAction() 
	{
		super(PlatformUI.getWorkbench().getActiveWorkbenchWindow(), new String("执行qmake"));
	
        projectsForQMake = new HashSet<String>();
	}

	/**
	 * 获取操作信息
	 */
	@Override
	protected String getOperationMessage() 
	{
		return new String("正在执行qmake");
	}

	/**
	 * 释放这一操作托管
	 */
	public void dispose() 
	{

	}

	/**
	 * 初始化
	 */
	public void init(IWorkbenchWindow window) 
	{

	}

	/**
	 * 从项目资源管理器视图的当前选择资源调用
	 */
	protected void invokeOperation(IResource resource, IProgressMonitor monitor) 
	{
		IProject project = resource.getProject();
		
		if (project == null) 
		{
			return;
		}
		
		if (!Utils.isCCFProject(project))
			return;
		
		String projectPath = project.getLocation().toString();
		
		if (projectsForQMake.contains(projectPath))
			return;
		
		projectsForQMake.add(projectPath);
		QMakeRunner.runQMake(project, monitor);
	}

	/**
	 * 获取当前编辑器CCF项目
	 * 如果焦点在任何编辑器外，则返回null。
	 * 如果当前编辑器项目为CCF项目，则返回该项目，否则，也返回null。
	 * @return
	 */
	private IProject projectOfActiveEditor() 
	{
		IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
		IEditorPart epart = page.getActiveEditor();
		IWorkbenchPart wpart = page.getActivePart();
		
		if (epart != null && epart.equals(wpart)) 
		{
			IEditorInput input = epart.getEditorInput();
			return Utils.projectOfEditorInput(input);
		}
	    return null;
	}

	/**
	 * 是否选中CCF项目
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private boolean isCCFProjectSelected() 
	{
		List<IResource> list = (List<IResource>) getActionResources();
		for (IResource resource : list) 
		{
			IProject project = resource.getProject();
			
			if (Utils.isCCFProject(project))
				return true;
		}
		return false;
	}
	
	/**
	 * 执行qmake
	 */
	public void run(IAction action) 
	{
		final IProject project = projectOfActiveEditor();
		
		if (project != null) 
		{ 
			IRunnableWithProgress op = new IRunnableWithProgress() 
			{
				public void run(IProgressMonitor monitor) 
				{
    			    QMakeRunner.runQMake(project, monitor);
				    monitor.done();
				}
			};
			try 
			{
				PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(true, false, op);
			} 
			catch (InterruptedException e) 
			{
				return;
			} 
			catch (InvocationTargetException e) 
			{
				Throwable realException = e.getTargetException();
				MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "错误：", realException.getMessage());
				return;
			}		
		} 
		else 
		{
			projectsForQMake.clear();
			run();
		}
	}
	
	/**
	 * 选中状态变化，或者当前编辑器改变
	 */
	public void selectionChanged(IAction action, ISelection selection) 
	{
		if (selection instanceof IStructuredSelection) 
		    selectionChanged((IStructuredSelection)selection);

		boolean enabled = projectOfActiveEditor() != null || isCCFProjectSelected();
		
		setEnabled(enabled);
		action.setEnabled(enabled);
	}
}
